{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "bc0fb058",
   "metadata": {},
   "outputs": [],
   "source": [
    "import torch\n", 
    "from tqdm import tqdm\n",
    "import numpy as np\n",
    "from skmultilearn.dataset import load_dataset\n",
    "from skmultilearn.dataset import available_data_sets\n",
    "from scipy.io import loadmat\n",
    "from sklearn.cluster import KMeans\n",
    "from skmultilearn.adapt import MLkNN\n",
    "from sklearn.neighbors import kneighbors_graph\n",
    "import sklearn\n",
    "from numpy.matlib import repmat\n",
    "import matplotlib.pyplot as plt\n",
    "import pandas as pd\n",
    "# Metrics\n",
    "from sklearn.metrics import coverage_error\n",
    "from sklearn.metrics import f1_score\n",
    "from sklearn.metrics import precision_score\n",
    "from sklearn.metrics import recall_score\n",
    "from sklearn.metrics import label_ranking_loss\n",
    "from sklearn.metrics import average_precision_score\n",
    "from sklearn.metrics import hamming_loss\n",
    "import scipy.sparse as sp\n",
    "from pathlib import Path\n",
    "import os\n",
    "import warnings\n",
    "warnings.filterwarnings('ignore')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "id": "f35c0c33",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU\n"
     ]
    }
   ],
   "source": [
    "## GPU or CPU\n",
    "GPU = False\n",
    "if GPU:\n",
    "    torch.backends.cudnn.enabled = True\n",
    "    torch.backends.cudnn.benchmark = True\n",
    "    os.environ['CUDA_VISIBLE_DEVICES'] = '0'\n",
    "    print(\"num GPUs\", torch.cuda.device_count())\n",
    "    dtype = torch.cuda.FloatTensor\n",
    "else:\n",
    "    dtype = torch.FloatTensor\n",
    "    print(\"CPU\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "406884e1",
   "metadata": {},
   "source": [
    "\n",
    "\\begin{align*}\n",
    "    \\normalsize{Multilabel \\hspace{0.1cm} Feature Selection \\hspace{0.1cm} With \\hspace{0.1cm} Constrained \\hspace{0.1cm} Latent \\hspace{0.1cm} Structure \\hspace{0.1cm} Shared \\hspace{0.1cm}Term}\n",
    "\\end{align*}\n",
    "\\begin{align*}\n",
    "    \\normalsize{(2021)}\n",
    "\\end{align*}\n",
    "$$\n",
    "\\begin{align*}\n",
    "    \\text{Wanfu  Gao, Yonghao Li, Liang  Hu }\n",
    "\\end{align*}\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6ea356f7",
   "metadata": {},
   "source": [
    "$\\normalsize{Updates \\hspace{0.1cm} Formulas:}$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "346a6e25",
   "metadata": {},
   "source": [
    "<div style=\"background-color: #EEEFFF; padding: 10px;\">\n",
    "\n",
    "\\begin{align*}\n",
    "    \\Large{V \\odot V \\frac{XQ + \\alpha YM^\\top + \\beta SV}{VQ^\\top Q + \\alpha VM M^\\top + \\beta AV}}\n",
    "\\end{align*}\n",
    "\n",
    "\\begin{align*}\n",
    "    \\Large{M \\odot M \\frac{V^\\top Y}{V^\\top VM}}\n",
    "\\end{align*}\n",
    "\n",
    "\\begin{align*}\n",
    "    \\Large{Q \\odot Q \\frac{X^\\top V}{QV^\\top V + \\gamma DQ}}\n",
    "\\end{align*}\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "75c01e5d",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "100%|██████████████████████████████████████████████████████████████████████████████████| 20/20 [06:32<00:00, 19.63s/it]\n"
     ]
    }
   ],
   "source": [
    "ERS = ['Science']\n",
    "\n",
    "dat = loadmat('../../../../Datasets/'+ ERS[0] + \".mat\")\n",
    "#     data = loadmat(\"Science.mat\")\n",
    "train = dat['train']\n",
    "test = dat['test']\n",
    "\n",
    "X_test = torch.from_numpy(train[0][0].T).to(torch.float32)\n",
    "Y_test = torch.from_numpy(train[0][1].T).to(torch.float32)\n",
    "Y_test[Y_test == -1] = 0\n",
    "\n",
    "X = torch.from_numpy(test[0][0].T).to(torch.float32).type(dtype)\n",
    "Xc = torch.from_numpy(test[0][0].T).to(torch.float32)\n",
    "XTX = X.T @ X\n",
    "\n",
    "Yc = torch.from_numpy(test[0][1].T).to(torch.float32)\n",
    "Yc[Yc == -1] = 0\n",
    "\n",
    "Y = Yc.type(dtype)\n",
    "#Feature\n",
    "n,d = X.shape\n",
    "#label\n",
    "n,c = Y.shape\n",
    "#local Structure\n",
    "nn = 5\n",
    "sigma = 30\n",
    "\n",
    "# #similarity & local Structure\n",
    "# S = kneighbors_graph(X, nn, mode='distance', include_self=False, metric='euclidean').todense()\n",
    "# S[S==0]=np.inf\n",
    "# S = np.array(np.exp(-S/(sigma)))\n",
    "# S = torch.from_numpy(S).to(torch.float32).type(dtype)\n",
    "# #Dii\n",
    "# Ds = torch.diag(torch.sum(S, dim=1))\n",
    "%run LocalStructure.ipynb\n",
    "S, Ds = LCS(X,sigma,nn)\n",
    "alpha=0.01\n",
    "beta=0.7\n",
    "gamma=0.9\n",
    "epsilon = torch.tensor(torch.finfo(torch.float32).eps)\n",
    "\n",
    "#Number of selected Latent\n",
    "k = 23\n",
    "\n",
    "# coefficient Matrix\n",
    "W = torch.rand(d,k).type(dtype)\n",
    "V = torch.rand(n,k).type(dtype)\n",
    "Q = torch.rand(d,k).type(dtype)\n",
    "M = torch.rand(k,c).type(dtype)\n",
    "# Number of Iteration & Parameters\n",
    "iteration = 30\n",
    "for o in range(iteration):\n",
    "    D = torch.diag(1 / (2 * torch.linalg.norm(Q, dim=1) + epsilon))\n",
    "    Va = X @ Q + alpha * (Y @ M.T) + beta * (S @ V)\n",
    "    Vb = (V @ Q.T @ Q + alpha*(V @ M @ M.T) + beta * (Ds @ V))\n",
    "    V = V * (Va) /torch.maximum((Vb),epsilon)\n",
    "    \n",
    "    Ma = V.T @ Y\n",
    "    Mb = (V.T @ V @ M)\n",
    "    M = M * ((Ma) / torch.maximum((Mb),epsilon))\n",
    "    \n",
    "    Qa = X.T @ V     \n",
    "    Qb = Q @ V.T @ V + gamma * (D @ Q)\n",
    "    Q = Q * ((Qa)/  torch.maximum((Qb),epsilon))\n",
    "    \n",
    "q = torch.linalg.norm(Q,axis=1)\n",
    "sQ = torch.argsort(q)\n",
    "\n",
    "for j in tqdm(range(20)):\n",
    "    j+=1\n",
    "    nosf = int (j * d / 100)\n",
    "    sX = Xc[:,sQ[d-nosf:].long()]\n",
    "    classifier = MLkNN(k=10)\n",
    "    classifier.fit(sX.numpy(), Yc.numpy())\n",
    "    #KNN\n",
    "    predictions = classifier.predict(X_test[:,sQ[d-nosf:]]).toarray()\n",
    "    scores = classifier.predict_proba(X_test[:,sQ[d-nosf:]]).toarray()\n",
    "\n",
    "    Mic = f1_score(Y_test, predictions, average='micro')\n",
    "    Mac = f1_score(Y_test, predictions, average='macro')\n",
    "    HML = hamming_loss(Y_test,predictions)\n",
    "    RNL = label_ranking_loss(Y_test,scores)\n",
    "    AVP = average_precision_score(Y_test.T,scores.T)\n",
    "    COV = coverage_error(Y_test,scores)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
